import axios, {
  type AxiosResponse,
  type InternalAxiosRequestConfig,
  type AxiosError,
} from "axios";
import { toast } from "sonner";
import useAuthStore from "@/store/auth";
import { tansParams } from "@/utils/ruoyi";
import cache from "@/utils/cache";
import { HttpStatus } from "@/enums/RespEnum";
import errorCode from "@/utils/errorCode";
import { router } from "@/router";

import {
  encryptBase64,
  encryptWithAes,
  generateAesKey,
  decryptBase64,
  decryptWithAes,
} from "@/utils/crypto";
import { encrypt, decrypt } from "@/utils/jsencrypt";

/* ---------------------------- 常量定义 ---------------------------- */
const encryptHeader = "encrypt-key"; // 请求头中携带加密密钥的字段

// 是否显示重新登录
export const isRelogin = { show: false };

/* ---------------------------- 全局 Header ---------------------------- */
export const globalHeaders = () => ({
  Authorization: "Bearer " + useAuthStore.getState().token,
  clientid: import.meta.env.VITE_APP_CLIENT_ID,
});

/* ---------------------------- axios 实例配置 ---------------------------- */
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
axios.defaults.headers["clientid"] = import.meta.env.VITE_APP_CLIENT_ID;

const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 50000,
});

/* ---------------------------- 请求拦截器 ---------------------------- */
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const authStore = useAuthStore.getState();

    // 是否携带 Token
    const isTokenDisabled = config.headers?.isToken === false;

    // 防重复提交
    const isRepeatDisabled = config.headers?.repeatSubmit === false;

    // 是否开启加密
    const isEncrypt = config.headers?.isEncrypt === "true";

    /* ---- Token 注入 ---- */
    if (authStore.token && !isTokenDisabled) {
      config.headers["Authorization"] = `Bearer ${authStore.token}`;
    }

    /* ---- GET 参数拼接 ---- */
    if (config.method === "get" && config.params) {
      let url = config.url + "?" + tansParams(config.params);
      url = url.endsWith("&") ? url.slice(0, -1) : url;
      config.params = {};
      config.url = url;
    }

    /* ---- 防重复提交逻辑 ---- */
    if (!isRepeatDisabled && ["post", "put"].includes(config.method || "")) {
      const requestObj = {
        url: config.url,
        data:
          typeof config.data === "object"
            ? JSON.stringify(config.data)
            : config.data,
        time: new Date().getTime(),
      };
      const sessionObj = cache.session.getJSON("sessionObj");
      const interval = 500; // ms

      if (
        sessionObj &&
        sessionObj.url === requestObj.url &&
        sessionObj.data === requestObj.data &&
        requestObj.time - sessionObj.time < interval
      ) {
        const msg = "数据正在处理，请勿重复提交";
        console.warn(`[${requestObj.url}] ${msg}`);
        return Promise.reject(new Error(msg));
      } else {
        cache.session.setJSON("sessionObj", requestObj);
      }
    }

    /* ---- 请求加密 ---- */
    if (import.meta.env.VITE_APP_ENCRYPT === "true") {
      if (isEncrypt && ["post", "put"].includes(config.method || "")) {
        const aesKey = generateAesKey();
        config.headers[encryptHeader] = encrypt(encryptBase64(aesKey));
        config.data =
          typeof config.data === "object"
            ? encryptWithAes(JSON.stringify(config.data), aesKey)
            : encryptWithAes(config.data, aesKey);
      }
    }

    /* ---- FormData 删除 Content-Type ---- */
    if (config.data instanceof FormData) {
      delete config.headers["Content-Type"];
    }

    return config;
  },
  (error: AxiosError) => {
    console.error("【请求拦截错误】", error);
    return Promise.reject(error);
  }
);

/* ---------------------------- 响应拦截器 ---------------------------- */
service.interceptors.response.use(
  (res: AxiosResponse) => {
    /* ---- 响应解密 ---- */
    if (import.meta.env.VITE_APP_ENCRYPT === "true") {
      const keyStr = res.headers[encryptHeader];
      if (keyStr) {
        try {
          const data = res.data;
          const base64Str = decrypt(keyStr);
          const aesKey = decryptBase64(base64Str.toString());
          const decryptData = decryptWithAes(data, aesKey);
          res.data = JSON.parse(decryptData);
        } catch (e) {
          console.error("响应解密失败：", e);
          toast.error("响应解密失败，请检查密钥配置");
        }
      }
    }

    /* ---- 状态码处理 ---- */
    const code = res.data?.code ?? HttpStatus.SUCCESS;
    const msg = errorCode[code] || res.data?.msg || errorCode["default"];

    // 二进制文件直接返回
    if (
      res.request.responseType === "blob" ||
      res.request.responseType === "arraybuffer"
    ) {
      return res.data;
    }

    // 登录过期
    if (code === HttpStatus.UNAUTHORIZED) {
      if (!isRelogin.show) {
        isRelogin.show = true;
        toast.error("登录状态已过期，请重新登录");
        // 使用 router.navigate 跳转到登录页
        router.navigate("/login");
      }
      return Promise.reject(new Error("登录过期"));
    }

    // 服务器错误
    if (code === HttpStatus.SERVER_ERROR) {
      toast.error(msg);
      return Promise.reject(new Error(msg));
    }

    // 警告
    if (code === HttpStatus.WARN) {
      toast.warning(msg);
      return Promise.reject(new Error(msg));
    }

    // 其他非成功状态
    if (code !== HttpStatus.SUCCESS) {
      toast.error(msg);
      return Promise.reject(new Error(msg));
    }

    // 成功返回数据
    return res.data;
  },
  (error: AxiosError) => {
    let message = error.message;

    const status = error.response?.status;

    if (status === HttpStatus.FORBIDDEN) {
      console.warn("403 权限不足");
      // navigateTo("/403");
    }

    if (message === "Network Error") {
      message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
      const code = message.slice(-3);
      message = `系统接口 ${code} 异常`;
    }

    toast.error(message);
    console.error("【响应错误】", error);
    return Promise.reject(error);
  }
);

/* ---------------------------- 导出 axios 实例 ---------------------------- */
export default service;
